function Offspring = SLMEA_GAhalf(Parent,Lower,Upper,Encoding,useGPU,Parameter)
% Genetic operators accelerated by GPU

%------------------------------- Copyright --------------------------------
% Copyright (c) 2025 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    %% Parameter setting
    if nargin > 5
        [proC,disC,proM,disM] = deal(Parameter{:});
    else
        [proC,disC,proM,disM] = deal(1,20,1,20);
    end
    Parent1 = Parent(1:floor(end/2),:);
    Parent2 = Parent(floor(end/2)+1:floor(end/2)*2,:);
    [N,D]   = size(Parent1);
 
    switch Encoding
        case 'binary'
            %% Genetic operators for binary encoding
            % One point crossover
            k = repmat(1:D,N,1) > repmat(randi(D,N,1),1,D);
            k(repmat(rand(N,1)>proC,1,D)) = false;
            Offspring    = Parent1;
            Offspring(k) = Parent2(k);
            % Bitwise mutation
            Site = rand(N,D) < proM/D;
            Offspring(Site) = ~Offspring(Site);
        otherwise
            %% Genetic operators for real encoding
            % Simulated binary crossover
            if ~useGPU
                beta = zeros(N,D);
                mu   = rand(N,D); 
            else 
                beta = gpuArray.zeros(N,D);
                mu   = gpuArray.rand(N,D);                
            end
            beta(mu<=0.5) = (2*mu(mu<=0.5)).^(1/(disC+1));
            beta(mu>0.5)  = (2-2*mu(mu>0.5)).^(-1/(disC+1));
            if ~useGPU
                beta = beta.*(-1).^randi([0,1],N,D);       
                beta(rand(N,D)<0.5) = 1;
                beta(repmat(rand(N,1)>proC,1,D)) = 1;                
            else
                beta = beta.*(-1).^gpuArray.randi([0,1],N,D);       
                beta(gpuArray.rand(N,D)<0.5) = 1;
                beta(repmat(gpuArray.rand(N,1)>proC,1,D)) = 1;                
            end
            Offspring = (Parent1+Parent2)/2+beta.*(Parent1-Parent2)/2;
            % Polynomial mutation
            Lower = repmat(Lower,N,1);
            Upper = repmat(Upper,N,1);
            if ~useGPU
                Site = rand(N,D) < proM/D;
                mu   = rand(N,D);                
            else
                Site = gpuArray.rand(N,D) < proM/D;
                mu   = gpuArray.rand(N,D);                
            end
            temp  = Site & mu<=0.5;
            Offspring       = min(max(Offspring,Lower),Upper);
            Offspring(temp) = Offspring(temp)+(Upper(temp)-Lower(temp)).*((2.*mu(temp)+(1-2.*mu(temp)).*...
                              (1-(Offspring(temp)-Lower(temp))./(Upper(temp)-Lower(temp))).^(disM+1)).^(1/(disM+1))-1);
            temp = Site & mu>0.5; 
            Offspring(temp) = Offspring(temp)+(Upper(temp)-Lower(temp)).*(1-(2.*(1-mu(temp))+2.*(mu(temp)-0.5).*...
                              (1-(Upper(temp)-Offspring(temp))./(Upper(temp)-Lower(temp))).^(disM+1)).^(1/(disM+1)));
            Offspring       = min(max(Offspring,Lower),Upper);              
    end
end